package backend;

import java.util.Calendar;

public class Task {
	int dd;
	int mm;
	int yy;
	int starttime;
	String strStartTime;
	int endtime;
	String strEndTime;
	String description;
	String venue;
	boolean haslabel;
	boolean hasImportance = false;
	String label;
	
	boolean alarm;
	enum State {OVERDUE,DONE,UPCOMING,NODATETIME};
	State curState;
	String curStateStr;


	public Task(){ //for creating empty task to use in TaskManager
		 dd = 0;
		 mm = 0;
		 yy = 0;
		 starttime = 0;
		 strStartTime = "0";
		 endtime = 0;
		 strEndTime = "0";
		 description = "-";
		 venue = "-";
		 haslabel = false;
		 hasImportance = false;
		 label = "-";
		 
		 alarm = false;
		 curState = State.UPCOMING;
	}
	
	/**
	 * This constructor creates a Task based on the necessary information as entered
	 * by the user.
	 * 
	 * @param day  Day, as entered by user. 1-31
	 * @param month  Month, as entered by user. 1-12
	 * @param year  Year, as entered by user. 00-99
	 * @param start  Start Time of a task. 0000-2359
	 * @param duetime  Due Time of a Task. 0000-2359
	 * @param labelname  Label of a task.
	 * @param impt  Indicates if a task is marked as Importance.
	 * @param task  Task Description as entered by the user.
	 * @param place  Venue of a task (if any).
	 * @param alarmOn  Indicates if the alarm is to be ON.
	 */
	public Task(int day, int month, int year, String start, String duetime, String labelname, boolean impt, String task, String place, boolean alarmOn){
		dd = day;
		mm = month;
		yy = year;
		starttime = Integer.parseInt(start);
		endtime = Integer.parseInt(duetime); 
		strStartTime = start;
		strEndTime = duetime;
		label = labelname;
  		
		if(!labelname.isEmpty()){
			haslabel = true;
		}
		
		hasImportance = impt;
		description = task.trim(); //remove white space from front and back
		venue = place;
		
		alarm = alarmOn;
		curState = State.UPCOMING;
		curStateStr = "UPCOMING"; 
		
		if(dd == 0 && mm == 0 && yy == 0 && starttime == 0 && endtime == 0) {
			curState = State.NODATETIME;
			curStateStr = "NODATETIME";
			alarm = false;
		}
	}

	/**
	 * The following get<information> methods allows the data stored to be accessed
	 * by other classes.
	 * 
	 * @return
	 */
	public int getDate() {
		return this.dd;
	}

	public int getMonth() {
		return this.mm;
	}

	public int getYear() {
		return this.yy;
	}
	
	public int getYear4() {
		return this.yy+2000;
	}

	public int getWholeDate() {
		return this.dd*10000 + this.mm*100 + this.yy;
	}

	public int getStartTime() { 
		return this.starttime;
	}
 
	public String getstrStartTime(){
		return this.strStartTime;
	}
 
	public String getstrEndTime(){
		return this.strEndTime;
	}
 
	public int getStartTimehours(){
		return (this.starttime/100);
	}
 
	public int getStartTimeminutes(){
		return (this.starttime%100);
	}

	public int getEndTime() {
		return this.endtime;
	}
	
	public int getEndTimeminutes(){
		return (this.endtime%100);
	}

	public String getDescription(){
		return this.description;
	}

	public boolean hasLabel(){
		return this.haslabel;
	}

	public boolean hasImportance() {
		return this.hasImportance;
	}

	public String getImportance() {
		String astr;
		if(hasImportance()) {
			astr = "* ";
			return astr;
		}
		return " ";
	}
	
	public String getLabel() {
		return this.label;
	}

	public String getVenue(){
		return this.venue;
	}
	
	public String getAlarmStatus() {
		if(alarm) return "on";
		return "off";
	}
	
	/**
	 * This method forms a String made up of the data stored in a particular task.
	 * 
	 * @return  All data stored in corresponding fields in a Task, in String format.
	 */
	public String printTask(){
		String taskToString = 
		""
		.concat(getImportance())
		.concat(getDateString("ddmmyy")).concat(" ")
		.concat(getstrStartTime()).concat(" ")
		.concat(getstrEndTime()).concat(" ")
		.concat(getDescription()).concat(" ")
	 	.concat(getLabel()).concat(" ")
	 	.concat(getVenue());

		return taskToString;
	}
	
	/**
	 * Same as the above, except that it has an addition field, Alarm.
	 * 
	 * @return  All data stored in corresponding fields in a Task (including Alarm), in String format.
	 */
	public String printTask_addIdentifier(){
		String taskToString = 
		""
		.concat(getImportance())
		.concat(getDescription()).concat(" ")
		.concat("#").concat(getDateString("ddmmyy")).concat(" ")
		.concat("@").concat(getstrStartTime()).concat("-").concat(getstrEndTime()).concat(" ")
	 	.concat(":").concat(getLabel()).concat(" ")
	 	.concat("$").concat(getVenue()).concat(" ")
	 	.concat("!").concat(getAlarmStatus());
			
		return taskToString;
		}	
	
	 /**
	 * Detects the format of the Date and format the date in the right format.
	 * If date is not Valid, empty String will be returned.
	 * @param astr  Date format as indicated by user.
	 * @return  Date, in correct format. Empty String if invalid Date. Error msg when no String format is given.
	 */
	public String getDateString(String astr){
		 if(astr == "yymmdd") {
			 String formatedDate =  String.format("%02d",getYear())+String.format("%02d",getMonth())+String.format("%02d",getDate());
			 if(formatedDate.equals("000000")) return "";
			 else return formatedDate; 
		 }
			 
		 if(astr == "ddmmyy") {
			 String formatedDate = String.format(String.format("%02d",getDate())+String.format("%02d",getMonth())+String.format("%02d",getYear()));
			 if(formatedDate.equals("000000")) return "";
			 else return formatedDate; 
		 }
		 return "no string format given";
	 }

	
	 public void clearAlarm(){
		 alarm = false;
	 }
	 
	 public boolean isAlarmOn(){
		 return alarm;
	 }
	 
	 
	/**
	 * Get the Date in the Calendar format for easy manipulation.
	 * 
	 * @return  Date in Calendar format.
	 */
	public Calendar getCal(){
		 Calendar taskCal = Calendar.getInstance(); 
		 taskCal.set(getYear4(), getMonth()-1, getDate(), getStartTimehours(), getStartTimeminutes(), 0); //note jan is zero, dec is 11!
		 return taskCal;
	 }
	 
	/**
	 * This method checks the state that the program is in.
	 * If viewing Upcoming task, it will be in UPCOMING State.
	 * 
	 * @return  Corresponding State.
	 */
	public State getState(){
		 if(curStateStr=="UPCOMING") {curState = State.UPCOMING; return State.UPCOMING;}
		 if(curStateStr=="OVERDUE") {curState = State.OVERDUE; return State.OVERDUE;}
		 if(curStateStr=="DONE") {curState = State.DONE; return State.DONE;}
		 if(curStateStr=="NODATETIME") {curState = State.NODATETIME; return State.NODATETIME;}
		 
		 return null;
	 }
	 
	/**
	 * Depending on the user's action and set the corresponding State of the program.
	 * If user enters "view upcoming", State of program will be set to UPCOMING.
	 * 
	 * @param newState  The corresponding State that the user is viewing in the program.
	 */
	public void setState(State newState){
		 if(newState==State.UPCOMING) curStateStr = "UPCOMING";
		 if(newState==State.OVERDUE) curStateStr = "OVERDUE";
		 if(newState==State.DONE) curStateStr = "DONE";
		 if(newState==State.NODATETIME) curStateStr = "NODATETIME";
	 }	
	 
	/**
	 * This method is used when Importing an XML file.
	 * It reads the corresponding State of a Task and allocates in according.
	 * 
	 * @param state  The State of a Task as indicated in the XML file.
	 */
	public void setState(String state){
		 
		 if(state.equals("UPCOMING")) {curStateStr = "UPCOMING"; curState = State.UPCOMING;}
		 if(state.equals("OVERDUE")) {curStateStr = "OVERDUE"; curState = State.OVERDUE;}
		 if(state.equals("DONE")) {curStateStr = "DONE"; curState = State.DONE;}
		 if(state.equals("NODATETIME")) {curStateStr = "NODATETIME"; curState = State.NODATETIME;}
		 
	 }
	 
}
